<!DOCTYPE html>
<html lang="zh-cn">
  <head>
    <meta charset="UTF-8">
    <title>Sucha's Blog - Archive for July, 2020</title>
    <meta name="generator" content="MarkdownProjectCompositor.lua">
    <meta name="author" content="Sucha">
    <meta name="keywords" content="suchang, programming, Linux, Lua">
    <meta name="description" content="Sucha's blog">
    <link rel="shortcut icon" href="../images/ico.png">
    <link rel="stylesheet" type="text/css" href="../styles/blog.css">
    <link rel="stylesheet" type="text/css" href="../styles/prism.min.css">
    <style id="site_theme"></style>
  </head>
  <body>
    <div id="body">
      <div id="text">
	   <!-- Page published by cmark-gfm begins here --><h1>Sucha's Blog ~ Archive for July, 2020</h1>
<p><a id="p5"></a></p>
<div class="date">20年7月25日 周四 11:22</div>
<h2>Curl 的 Lua 绑定，以及 multi 接口</h2>
<p>尝试了一下 curl 发送请求的 multi 接口，另外的 easy 接口是一个阻塞的设计，将 easy handle
放到 multi 中后，变成了非阻塞的接口。</p>
<p>大概是下面这样的逻辑，是非阻塞的，目前遇到的遗憾，是 perform 以及 wait 都没法知道具体是哪一个
easy handle 请求结束了。</p>
<pre><code class="language-lua">easy = curl.easy()
easy:setopt(...) -- custom request header, response header, body reader
multi = curl.multi()
multi.add_handle(easy)
repeat
    multi.perform()
untile multi.wait() &lt;= 0
</code></pre>
<p>另外还试了一下 curl 中的 event-driven 接口，其实也还是 multi，但是区别于 multi.wait() 基于
底层 select 的设置，这里的 event-driven，依赖比如 libuv、libevent，以及我想集合进去的 mnet 的
事件循环。</p>
<p>创建这种 event-driven 的 curl 程序，还需要需要底层提供一个 timeout 的回调，也许是创建 socket connect 后，
回调具体的 fd，有了这个 fd 才能将其加入到 epoll、kqueue 里面去。</p>
<p>但是我自己验证的结果，感觉程序上跟 github 里面的 example 已经很像了，但一些请求没能成功。</p>
<p>这种方式需要设置好几个回调，在这个基础上设计中间件太复杂了，不管是输入的 header、post data，还是回调拿到 header、
body data 都太复杂了。</p>
<p>另外这种 event-driven 的方式还有一些隐含的条件，比如 timer 是独立于 fd 的，在 fd 前面就创建了，而且 timeout 的单位是 micro seconds，这其实是一个精度很高的 timer 了。</p>
<p>这里我也有疑惑，比如对于 curl 来说，这里的 event-driven 只是借用了 epoll、kqueue 的内核事件机制，我不大理解为何需要由 curl 来
创建 socket，为何不是更底层来管理 socket fd，其实参数交给 curl 来设置都可以，底层只是保证非阻塞就可以了。而 curl 更多的是面向 HTTP 这一层的中间件，raw data &lt;-&gt; HTTP structure data 的转换。</p>
<p>但不管怎么说，curl 这套东西还是太香了，毕竟每个发行版都有，每个发行版安装 dev 或者 command line tool 之后，有了头文件，就可以立马基于 libcurl 这个库进行发开发了。</p>
<p>因为自测 event-driven 没成功，相关信息也比较少，最后是用了上面 multi 接口包裹 easy 接口的非阻塞式设计，用了 <a href="https://github.com/Lua-cURL/Lua-cURLv3.git">Lua-cURLv3</a> 这个库，就请求而言，单独使用了 select。</p>
<div class="category"><a href="CategoryProgramming.html">CategoryProgramming</a> / <a href="2020-07.html#p5">Permalink</a> / <a href="https://github.com/lalawue/homepage/discussions/categories/blog" target="_blank">Discussion</a></div>
<p><a id="p4"></a></p>
<div class="date">20年7月25日 周四 11:22</div>
<h2>HTML 的 Content-Type: multipart/form-data</h2>
<p>研究了一下，Mac 下轮着 Safari、Chrome、FireFox 前后台调通后，这里大概记录一下吧。</p>
<h3>前端页面 HTML</h3>
<p>在前端 HTML 的写法是，form 里面指定 enctype 为 &quot;multipart/form-data&quot;，如下</p>
<pre><code class="language-html">&lt;form class=&quot;cell&quot; action=&quot;&quot; method=&quot;POST&quot; enctype=&quot;multipart/form-data&quot;&gt;
    &lt;input type=&quot;file&quot; name=&quot;myfile&quot; /&gt;
    &lt;input type=&quot;submit&quot; /&gt;
&lt;/form&gt;
</code></pre>
<h3>后端解析</h3>
<p>假设在浏览器里面点击 &quot;file&quot; 按钮，选择发送的是一个 PDF 文件，协议上收到是下面这样的，... 是省略：</p>
<pre><code class="language-http">POST /path HTTP/1.1
...
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary5WeF4Lu8GyQKEIE5
Accept-Language: zh-cn

------WebKitFormBoundary5WeF4Lu8GyQKEIE5
Content-Disposition: form-data; name=&quot;myfile&quot;; filename=&quot;noname.pdf&quot;
Content-Type: application/pdf

%PDF-1.3
...
%%EOF

------WebKitFormBoundary5WeF4Lu8GyQKEIE5--
</code></pre>
<p>我自己没有试过多文件，但是从网上资料看，多文件跟单文件不同的是，前面一个 boundary 结束符后，再来一个 boundary 的 Disposition 描述分割，开启下一个数据块的传输。</p>
<p>代码部分就不贴了，感觉有点挫，考虑了多文件分割，以及需要传递给用户文件名、类型等信息，最后是使用了阶段状态的描述，毕竟后端收到的数据是不定长的输入。</p>
<p>--</p>
<p>最后还是整了一下代码，加入了 builder，在 <a href="https://github.com/lalawue/multipart-formdata-lib">multipart-formdata-lib</a>.</p>
<div class="category"><a href="CategoryProgramming.html">CategoryProgramming</a> / <a href="2020-07.html#p4">Permalink</a> / <a href="https://github.com/lalawue/homepage/discussions/categories/blog" target="_blank">Discussion</a></div>
<p><a id="p3"></a></p>
<div class="date">20年7月16日 周四 12:04</div>
<h2>LuaRocks with LuaJIT</h2>
<p>标准版的 LuaRocks 只有原版的 Lua 可以配套使用，torch 为了让 LuaRocks 能够支持 LuaJIT，修改了一个版本，其实只是修改了编译过程，毕竟 LuaJIT 完整支持 Lua 5.1 的语法。</p>
<p>torch 的版本支持 LuaJIT 的各个版本，但最新的只到 2.1 beta2。早上我将 LuaJIT 的支持版本升级到了 2.1 beta3，地址是 <a href="https://github.com/lalawue/luajit-rocks">luajit-rocks</a>，然后还发了一个 pull request。但是这个项目有好几年没有更新了，不晓得会不会有 maintainer 会注意到。</p>
<p>torch 的 luajit 其实还有修改 2 个地方，一个是 string 的 hash 方案，一个加入了交互用的 readline。交互部分明显有改善，而 hash 部分不晓得为什么要这么改，应该也还好吧，反正为了 pull request 这里我是不敢动的。hash 用的是 <a href="https://github.com/amadvance/tommyds">tommy 的方案</a>。</p>
<p>在 Linux 中编译了一把，顺利通过，后面再看需要安装吧。在自己的 MacBook Pro 上安装好后，install 了 busted 和 moonscript。不得不说，其实是为了试一下 moonscript，硬是找到了 LuaRocks 的 LuaJIT based 方案。</p>
<p>先用一阵子再说吧。</p>
<div class="category"><a href="CategoryMisc.html">CategoryMisc</a> / <a href="2020-07.html#p3">Permalink</a> / <a href="https://github.com/lalawue/homepage/discussions/categories/blog" target="_blank">Discussion</a></div>
<p><a id="p2"></a></p>
<div class="date">20年7月15日 周三 22:38</div>
<h2>MacOS 下使用 BitBar 在状态栏自定义信息</h2>
<p>如果自己有一些信息需要通过点击状态栏图标后获得，或者通过点击状态栏图标启动、关闭的，都可以使用这个工具 <a href="https://getbitbar.com">BitBar</a> 来操作。</p>
<p>安装好后，只需要定义 plugin 目录，然后在 plugin 目录下加入功能脚本就可以了。脚本其实只关注输出的文本，操作部分其实是通过特殊命令来定义的。</p>
<p>比如例子中的 refresh.sh，精简后是下面这样：</p>
<pre><code class="language-bash">if [[ &quot;$1&quot; = &quot;restart&quot; ]]; then
osascript &lt;&lt;EOD
	tell application &quot;BitBar&quot; to quit
	delay 1
	tell application &quot;BitBar&quot; to activate
EOD
fi

echo &quot;↻&quot;
echo &quot;---&quot;
echo &quot;Refresh Me| terminal=false refresh=true&quot;
echo &quot;Restart Bitbar| bash='$0' param1=restart terminal=false&quot;;
</code></pre>
<p>会在状态栏显示一个圆圈刷新，点击后下拉菜单会有 &quot;Refresh Me&quot; 以及 &quot;Restart Bitbar&quot;。</p>
<ul>
<li>Refresh Me 是第一项，'|' 后定义功能动作，不新开一个 shell，刷新菜单</li>
<li>Restart Bitbar 是第二项，bash 定义使用到的脚本或者程序，‘$0' 就是 Bitbar 自己了，参数是 &quot;restart&quot;，其实是关闭然后再重启这个 refresh.sh，简简单单的 bash shell 语法了</li>
</ul>
<p>可惜的是我虽然弄懂了一点点如何编写这个 Bitbar 的 plugin 命令，但是通过 Bitbar 控制的程序最后没有符合我的预期，:-(</p>
<div class="category"><a href="CategoryLinux.html">CategoryLinux</a> / <a href="2020-07.html#p2">Permalink</a> / <a href="https://github.com/lalawue/homepage/discussions/categories/blog" target="_blank">Discussion</a></div>
<p><a id="p1"></a></p>
<div class="date">20年7月14日 周二 11:34</div>
<h2>GitHub 定义 Repo 语言</h2>
<p>之前写的 <a href="https://github.com/lalawue/LWTheme">LWTheme</a> 兼顾 Swift/ObjC 语言，GitHub 改版后，在 repo 里面没有语言百分比的显示了。</p>
<p>搜了一下，可以在 branch 里面定义 .gitattributes 文件，里面这样写</p>
<pre><code class="language-source">*.swift linguist-language=Swift
</code></pre>
<p>自测了一把，网站只会读取 default branch 里面的 .gitattributes，切换其他 branch 没有用。</p>
<div class="category"><a href="CategoryMisc.html">CategoryMisc</a> / <a href="2020-07.html#p1">Permalink</a> / <a href="https://github.com/lalawue/homepage/discussions/categories/blog" target="_blank">Discussion</a></div>
<p><a id="p0"></a></p>
<div class="date">20年7月9日 周四 15:44</div>
<h2>OpenVPN 配置记录</h2>
<p>其实考虑过几个比如 ShadowSocks 之类的，但是很不稳定，考虑最后也许还是用 VPN 来得稳妥一些，折腾了半天，终于跑通，先这里随便记录一下吧。</p>
<p>大概分两个部分，一个是服务端的配置，一个是客户端的配置。</p>
<ul>
<li>Ubuntu 下先 apt-get install openvpn</li>
<li>然后<a href="https://article.itxueyuan.com/pMy1b">生成服务端、客户端的密钥</a>，比如 ca、server key、client key、dh</li>
<li>接着<a href="http://blog.joylau.cn/2020/05/28/OpenVPN-Config/">服务端软件配置 server.config</a>，其实主要是上述密钥的配置，以及日志等文件位置，以及刚开始试运行时设置日志打印的密度</li>
<li>还有<a href="https://wiki.deepin.org/wiki/VPN%E6%9C%8D%E5%8A%A1">服务端系统配置</a>， 比如 iptables 配置转发</li>
<li>最后<a href="http://blog.joylau.cn/2020/05/28/OpenVPN-Config/">客户端软件配置</a>，大体上只是配置服务端 ip 地址，密钥就可以了</li>
</ul>
<p>客户端我在 Mac 下用的是 TunnelBlick，速度其实一般，还没长时间使用，后续先观察一阵。</p>
<div class="category"><a href="CategoryMisc.html">CategoryMisc</a> / <a href="2020-07.html#p0">Permalink</a> / <a href="https://github.com/lalawue/homepage/discussions/categories/blog" target="_blank">Discussion</a></div>
<!-- Page published by cmark-gfm ends here -->
  <div id="foot">2004-<script>var d = new
	Date();document.write(d.getFullYear())</script> &copy;
	Sucha. Powered by MarkdownProjectCompositor.
  </div>
  </div><!-- text -->
  <div id="sidebar">
  </div><!-- sidebar -->
  <script src="../js/prism.min.js" async="async"></script>
  <script src="../js/blog_sidebar.js"></script>
  </div> <!-- body -->
</body>
</html>